/*
 * @Author: sympsel sympsel@outlook.com
 * @Date: 2025-09-23 08:20:06
 * @LastEditors: sympsel sympsel@outlook.com
 * @LastEditTime: 2025-09-25 23:58:21
 * @FilePath: \work25_9_23_2\include\List.h
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置:
 * https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#ifndef LIST_H
#define LIST_H

#include <iostream>
#include <stdexcept>
using std::cout;
using std::endl;

template <class T = int>
class List {
   public:
    friend std::ostream& operator<<(std::ostream& out, const List<T>& list) {
        out << "[";
        int end = list._size - 1;
        if (end != -1) {
            for (int i = 0; i < end; ++i) {
                out << list._data[i] << ", ";
            }
            out << list._data[end];
        }
        out << "]";
        return out;
    }
    List(int capacity = 8) : _capacity(capacity), _size(0), _data(new T[_capacity]) {}

    List(const List<T>& list)
        : _capacity(list._capacity), _size(list._size), _data(new T[list._capacity]) {
        for (int i = 0; i < _size; ++i) {
            _data[i] = list._data[i];
        }
    }

    ~List() { delete[] _data; }

    List<T>& operator=(const List<T>& list) {
        if (this != &list) {
            delete[] _data;
            _data = new T[_capacity = list._capacity];
            _size = list._size;
            for (int i = 0; i < _size; ++i) {
                _data[i] = list._data[i];
            }
            return *this;
        }
        return *this;
    }

    void clear() { _size = 0; }

    const int& size() const { return _size; }

    const int& capacity() const { return _capacity; }

    bool empty() {return _size == 0; }

    void append(T value) {
        enableCapacity();
        _data[_size++] = value;
    }

    void remove() {
        if (_size == 0) {
            throw std::runtime_error("the List is empty.");
        }
        --_size;
    }

    void remove(int index) {
        if (_size == 0) {
            throw std::runtime_error("the List is empty.");
        }
        if (index >= _size || index < 0) {
            throw std::out_of_range("the index out_of_range.");
        }
        for (int i = index; i < _size - 1; ++i) {
            _data[i] = _data[i + 1];
        }
        --_size;
    }

    void removeFirst() { remove(0); }

    void insert(T value, int index) {
        if (index > _size || index < 0) {
            throw std::out_of_range("the index out_of_range");
        }
        for (int i = _size; i > index; --i) {
            _data[i] = _data[i - 1];
        }
        ++_size;
        _data[index] = value;
    }

    void insert(const T& value) { insert(value, 0); }

    const T& indexAt(int index) const {
        if (index >= _size || index < 0) {
            throw std::out_of_range("index out_of_range");
        }
        return _data[index];
    }

    T& operator[](int index) const { return _data[index]; }

   private:
    int _capacity;
    int _size;
    T* _data;

    void enableCapacity() {
        if (_size >= _capacity) {
            _capacity *= 2;
            T* data = new T[_capacity];
            for (int i = 0; i < _size; ++i) {
                data[i] = _data[i];
            }
            delete[] _data;
            _data = data;
        }
    }
};

#endif  // LIST_H